﻿using BrnMall.WeiXin.Sdk;
using CJiaBao.Core.Utils;
using Core.Configuration.Api;
using Core.Configuration.Config;
using Core.Configuration.Helper;
using Core.Sdk.WeiXin;
using Core.Sdk.WeiXin.Tool;
using IconYuan.Api.Services;
using IconYuan.Manager.Users;
using IconYuan.Model.DTO.Account;
using IconYuan.Model.DTO.Users;
using IconYuan.Model.Entity.Users;
using IP2Region.Net.XDB;
using Microsoft.AspNetCore.Mvc;

namespace IconYuan.Api.Controllers.Users
{
    /// <summary>
    /// 账户登录操作
    /// </summary>
    public class PassportController : ApiBase
    {
        UserManager userSvc;
        OauthManager oauthSvc;
        UserGradeManager gradeSvc;
        UserDetailManager userDetailSvc;
        public PassportController()
        {
            oauthSvc = new OauthManager();
            userSvc = new UserManager();
            gradeSvc = new UserGradeManager();
            userDetailSvc = new UserDetailManager();
        }

        ///// <summary>
        ///// 手机号+密码登录
        ///// </summary>
        //[HttpGet]
        //public async Task<UserInfoDto> Login(string mobile, string pwd)
        //{
        //    var oauth = await oauthSvc.LoginOpenId(mobile, 3);
        //    if (!oauth.unionid.Equals(pwd)) throw new Exception("用户名密码不正确");

        //    return await GetUserInfo(oauth);
        //}

        /// <summary>
        /// 微信手机号登录
        /// </summary>
        /// <returns>返回用信息，其中user_type: 0 会员,1 工作人员, 2 老板</returns>
        /// <exception cref="Exception"></exception>
        [HttpPost]
        public async Task<UserInfoDto> WxLogin([FromBody] WxLoginDto model)
        {
            WeiXinSdk.Log($"Url:{GetAbsoluteUri(Request)}");

            var wxUser = await GetPhoneNumber(model.code, model.encryptedData, model.iv);
            if (wxUser == null) throw new Exception("登录失败");

            var oauth = await oauthSvc.LoginByMobile(wxUser.mobile, 1);
            if (oauth == null)
            {
                if (GetStoreId() <= 0) throw new Exception("缺少店铺id");
                //注册用户
                var userInfo = await InsertUser(wxUser.mobile, model.parent_id);
                if (userInfo?.user_id <= 0) throw new Exception("注册失败");

                //注册授权信息
                oauth = new Oauth()
                {
                    mobile = wxUser.mobile,
                    open_id = wxUser.open_id,
                    user_id = userInfo.user_id,
                    unionid = string.Empty,
                    store_id = GetStoreId(),
                    create_time = DateTime.Now,
                    oauth_type = 1,
                };
                oauth.id = await oauthSvc.InsertAsync(oauth);
            }

            if (oauth?.id <= 0) throw new Exception("授权信息注册失败");

            WeiXinSdk.Log($"登录更新:uid:{oauth.user_id}, new_openid:{wxUser.open_id},old_openid:{oauth.open_id}, 触发修改：{!oauth.open_id.Equals(wxUser.open_id)}");
            //换手机登录时,更新当前openid
            if (!oauth.open_id.Equals(wxUser.open_id))
            {
                await oauthSvc.UpdateAsync(x => new Oauth { open_id = wxUser.open_id }, y => y.id == oauth.id);
            }
            
            return await GetUserInfo(oauth);
        }
 
        private async Task<Oauth> GetPhoneNumber(string code, string encryptedData, string iv)
        {
            var session = await WeiXinSdk.GetSessionResult(code, Config.AppId, Config.AppSecret);
            if (session == null) throw new Exception("code解析失败");

            var wxUser = WeiXinSdk.DecryptUserInfo(session.Session_Key, encryptedData, iv);
            if (wxUser == null) throw new Exception("手机号解析失败");
            return new Oauth()
            {
                open_id = session.OpenId,
                mobile = wxUser.PhoneNumber
            };
        }

        private async Task<User> InsertUser(string mobile, int parent_id)
        {
            //店铺默认等级
            var grade = gradeSvc.Get(x => x.is_default == 1 && x.store_id == GetStoreId()) ?? new UserGrade();
            var gradeExt = string.IsNullOrEmpty(grade.ext?.Trim()) ? null : JsonHelper.ToObject<GradeExt>(grade.ext);
            if (gradeExt == null)
                gradeExt = new GradeExt();

            var user = new User()
            {
                mobile = mobile,
                nick_name = mobile,
                grade_id = grade.grade_id,
                balance = gradeExt.balance,
                points = gradeExt.points,
                brokerage_ratio = gradeExt.brokerage_ratio,
                parent_id = parent_id,
                pay_money = 0,
                avatar_id = 0,
                address_id = 0,
                is_delete = 0,
                user_type = 0,
                store_id = GetStoreId(),
                ip = GetIP(),
                avatar = "images/logo.png",
                last_time = DateTime.Now,
                create_time = DateTime.Now,
                expire_time = DateTime.Now.AddDays(grade.days)
            };
            user.user_id = await userSvc.InsertAsync(user);
            return user;
        }

        private async Task<UserInfoDto> GetUserInfo(Oauth oauth)
        {
            var user = await userSvc.GetAsync<UserBase>(oauth.user_id);
            var userDetail = await userDetailSvc.GetAsync(x => x.user_id == user.user_id) ?? new UserDetail() { user_id = user.user_id };
            user.ip = GetIP();
            //保存登录IP
            await userSvc.UpdateAsync(x => new User { ip = user.ip }, y => y.user_id == user.user_id);

            return DtoHelper.ToUserInfoDto(user, userDetail, null);
        }
    }
}
